;=================================================
; unit test framework sample
;

;=================================================
; here can be any function - this introduced just as a sample
(defun my-plus (&rest args)
 "this is a sample test function, which is actually the same `+' operator"
 ; moduling plus
 (eval (append (list '+) args))
 )

;=================================================
; stores the test-case's name
(defvar *test-name* nil)

;=================================================
; just provides the correct description for test case
; using the global variable *test-name*
(defmacro deftest (name parameters &body body)
  "Define a test function. Within a test function we can call
   other test functions or use 'check' to run individual test
   cases."
  `(defun ,name ,parameters
    (let ((*test-name* (append *test-name* (list ',name))))
      ,@body)))

;=================================================
; combines test forms
(defmacro check (&body forms)
  "Run each expression in 'forms' as a test case."
  `(combine-results
    ,@(loop for f in forms collect `(report-result ,f ',f))))

;=================================================
;
(defmacro combine-results (&body forms)
 (with-gensyms (result)
  `(let ((result t))
      (list 'b 'c)
      ,@(loop for f in forms collect `(unless ,f (setf result nil)))
      result
      )
  )
 )

;=================================================
; reports about the particular test case
(defun report-result (result form)
  "Report the results of a single test case. Called by 'check'."
  (format t "~:[FAIL~;pass~] ... ~a: ~a~%" result *test-name* form)
  result)




;=================================================
; several test functions
(defun test-+ ()
  (check
    (= (+ 1 2) 3)
    (= (+ 1 2 3) 6)
    (= (+ -1 -3) -4)))

(defun test-* ()
    (check
      (= (* 2 2) 4)
      (= (* 3 5) 15)))

;=================================================
; an empty thunk
(defmacro no (&rest args) nil)

;=================================================
; test
;
(defun test ()
 ; 1
 (test-+)
 (test-*)
 )

;=================================================
; app entry point
;
(defun main ()

 (format t "unit test framework sample~%=====~%")

 (test)

 (exit)
 )

;=================================================
; executes main
;
(main)

